/*
 * GPS_SatelliteData.c
 *
 *  Created on: 2015-10-8
 *      Author: Administrator
 */

#include "GPS_SatelliteData.h"
#include "MxxTimer.h"
#include "DSP281x_GlobalPrototypes.h"
#include "GPS_Multiply_By.h"



const unsigned char NumToAscii[16] =
					{'0','1','2','3',
					 '4','5','6','7',
					 '8','9','A','B',
					 'C','D','E','F'};


//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("UserDataFile")
#else
#pragma DATA_SECTION(CurrGpsInfo,"UserDataFile");
#endif
GPS_INFO CurrGpsInfo;

//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("UserDataFile")
#else
#pragma DATA_SECTION(tmpGpsInfo,"UserDataFile");
#endif
GPS_INFO tmpGpsInfo;


//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("UserDataFile")
#else
#pragma DATA_SECTION(YSGpsBuf,"UserDataFile");
#endif
Uns YSGpsBuf[256];


/*
	2012-04-18: 在无效时取消判断经纬度数据长度
*/
/*
  Table 1.1 – NMEA-0183 Output Messages
    NMEA    Record Description
	----    -----------------------------------------
    GGA     Global positioning system fixed data
    GLL     Geographic position – latitude/longitude
    GSA     GNSS DOP and active satellites
    GSV     GNSS satellites in view
    RMC     Recommended minimum specific GNSS data
    VTG     Course over ground and ground speed3

  RMC:
      Table 1.9 – RMC Data Format
  Name                Example         Units Description
  --------------------------------------------------------------------
  Message ID          $GPRMC RMC      protocol header
  UTC position        161229.487      hhmmss.sss
  Status              A               A=data valid or V data not valid
  Latitude            3723.2475       ddmm.mmmm
  N/S Indicator       N               N=north or S=south
  Longitude           12158.3416      dddmm.mmmm
  E/W                 W               E=east or W=west
  Speed Over Ground   0.13            knots
  Course Over Ground  309.62          degrees True
  Date                120598          ddmmyy
  Magnetic Variation                  degrees
  Magnetic E/W                        E=east or W=west
  Checksum            *10
  <CR><LF>                            End of message termination

 MessageID后字段含义：
  字段1：UTC时间，hhmmss.sss格式
  字段2：状态，A=定位，V=未定位
  字段3：纬度ddmm.mmmm，度分格式（前导位数不足则补0）
  字段4：纬度N（北纬）或S（南纬）
  字段5：经度dddmm.mmmm，度分格式（前导位数不足则补0）
  字段6：经度E（东经）或W（西经）
  字段7：速度，节，Knots
  字段8：方位角，度
  字段9：UTC日期，DDMMYY格式
  字段10：磁偏角，（000 - 180）度（前导位数不足则补0）
  字段11：磁偏角方向，E=东W=西
  字段12：校验值
*/

#pragma CODE_SECTION(GPS_NMEA_YsHandler, "FuncsMap2H0SARam")
Uns GPS_NMEA_YsHandler(GPS_INFO *Info, Uns *Buf, Uns DataLen)
{
  volatile Uns temp, Chk1, Chk2, i, *P;
  GPS_INFO tmpInfo;
  volatile Uns ID, Type;
  volatile Uns ACnt, OCnt, DCnt, WCnt;
  Uns Cnts[64];

  //数据可发往原始数据口及母板（供记录板）
  //....

  if (DataLen < 20)
    return (0);
  Type = 0;
  temp = GPS_CheckSum(Buf + 1, DataLen - 6);
  Chk1 = NumToAscii[temp >> 4];
  Chk2 = NumToAscii[temp & 0x0F];
  if ((Chk1 == Buf[DataLen - 4]) && (Chk2 == Buf[DataLen - 3]))
  {
    ID = 0;
	ACnt = 0;
	OCnt = 0;
	for (i = 0; i < 64; i++)
      Cnts[i] = 0;
	//先检查各字段长度
	for (i = 0; i < DataLen - 2; i++)
	{
      if (Buf[i] == ',')
	  {
		Cnts[ID++] = ACnt;
		ACnt = 0;
		if ((ID == 1) && (i == 6))
        {
		  if ((Buf[1] == 'G') && (Buf[2] == 'P'))
          {
            if ((Buf[3] == 'R') && (Buf[4] == 'M') && (Buf[5] == 'C'))
		      Type = GPS_RMC;
			else if ((Buf[3] == 'G') && (Buf[4] == 'G') && (Buf[5] == 'A'))
		      Type = GPS_GGA;
			else if ((Buf[3] == 'G') && (Buf[4] == 'L') && (Buf[5] == 'L'))
		      Type = GPS_GLL;
			else if ((Buf[3] == 'G') && (Buf[4] == 'S') && (Buf[5] == 'A'))
		      Type = GPS_GSA;
			else if ((Buf[3] == 'G') && (Buf[4] == 'S') && (Buf[5] == 'V'))
		      Type = GPS_GSV;
			else if ((Buf[3] == 'V') && (Buf[4] == 'T') && (Buf[5] == 'G'))
		      Type = GPS_VTG;
			else
			  return (0);
		  }
		  else
		    return (0);
		}
	  }
	  else
	    ACnt++;
	}
	if (Type == GPS_RMC)
	{
	  if (Cnts[0] != 6)//$GPRMC,etc
	    return (0);

		///2013-07-15: 可能没有时间域，需要判断此情况
	  	///if ((Cnts[1] != 10) && (Cnts[1] != 9))//hhmmss.sss
		if ((Cnts[1] != 10) && (Cnts[1] != 9) && (Cnts[1] != 0))///hhmmss.sss,或者hhmmss.ss,或者没有时间
	    	return (0);

	  if (Cnts[2] != 1)//A,V
	    return (0);
	  /*if (Cnts[3] != 9)//Latitude
	    return (0);
	  if (Cnts[4] != 1)//N/S
	    return (0);
	  if (Cnts[5] != 10)//Longitude
	    return (0);
	  if (Cnts[6] != 1)//E/W
	    return (0);*/
	  /*if (Cnts[7] != 4)//Speed
	    return (0);
	  if (Cnts[8] != 4)//Course
	    return (0);*/
	  /*if (Cnts[9] != 6)//Date
	    return (0);*/
    }

	P = (Uns *)&tmpInfo;
    for (i = 0; i < sizeof(GPS_INFO); i++)
	  *P++ = 0x0000;
	ID = 0;
	ACnt = 0;
	DCnt = 0;
	WCnt = 0;
    for (i = 0; i < DataLen - 2; i++)
	{
	  if (Buf[i] == ',')//
      {
        ID++;
		WCnt = 0;
	  }
	  else
	  {
        switch (Type)
		{
          case GPS_RMC:
		    switch (ID)
			{
              case 1:
			    switch (i)
				{
                  case 7:
				    tmpInfo.Time.Hour = MULTIPLY_BY_10(Buf[i] - 0x30);
					break;
				  case 8:
				    tmpInfo.Time.Hour += (Buf[i] - 0x30);
					break;
				  case 9:
				    tmpInfo.Time.Minute = MULTIPLY_BY_10(Buf[i] - 0x30);
					break;
				  case 10:
				    tmpInfo.Time.Minute += (Buf[i] - 0x30);
                    break;
				  case 11:
				    tmpInfo.Time.Second = MULTIPLY_BY_10(Buf[i] - 0x30);
					break;
				  case 12:
				    tmpInfo.Time.Second += (Buf[i] - 0x30);
					break;
				  case 13://Dot
				    break;
				  default:
				    break;
				}
			    break;
			  case 2://Status--'A' or 'V'
			    tmpInfo.State = Buf[i];
			    break;
			  case 3://Lattitude
			    if (Buf[i] != '.')
			    switch (ACnt)
				{
				  case 0:
				  case 2:
				  case 4:
				  case 6:
				    tmpInfo.Latitude[WCnt] = (Buf[i] - 0x30) << 4;
					ACnt++;
					break;
				  case 1:
				  case 3:
				  case 5:
				    tmpInfo.Latitude[WCnt] += (Buf[i] - 0x30);
					WCnt++;
					ACnt++;
					break;
				  case 7:
				    tmpInfo.Latitude[WCnt] += (Buf[i] - 0x30);
					WCnt++;
					ACnt++;
					break;
				  default:
				    break;
				}
			    break;
			  case 4://N/S
			    tmpInfo.N_S = Buf[i];
			    break;
			  case 5://Longitude
			    if (Buf[i] != '.')
				switch(OCnt)
				{
                  case 0:
				    tmpInfo.Longitude[WCnt++] = Buf[i] - 0x30;
					OCnt++;
				    break;
				  case 1:
				  case 3:
				  case 5:
				  case 7:
				    tmpInfo.Longitude[WCnt] = (Buf[i] - 0x30) << 4;
					OCnt++;
				    break;
				  case 2:
				  case 4:
				  case 6:
				    tmpInfo.Longitude[WCnt] += (Buf[i] - 0x30);
					WCnt++;
					OCnt++;
					break;
				  case 8:
				    tmpInfo.Longitude[WCnt] += (Buf[i] - 0x30);
					WCnt++;
					OCnt++;
				    break;
				  default:
				    break;
				}
			    break;
			  case 6://E/W
			    tmpInfo.E_W = Buf[i];
			    break;
			  case 7://Speed
			    break;
			  case 8://Course
			    break;
			  case 9://Date
			    switch (DCnt)
				{
				  case 0:
				    tmpInfo.Time.Date = MULTIPLY_BY_10(Buf[i] - 0x30);
					DCnt++;
				    break;
				  case 1:
				    tmpInfo.Time.Date += (Buf[i] - 0x30);
					DCnt++;
					break;
				  case 2:
				    tmpInfo.Time.Month = MULTIPLY_BY_10(Buf[i] - 0x30);
					DCnt++;
					break;
				  case 3:
				    tmpInfo.Time.Month += (Buf[i] - 0x30);
					DCnt++;
					break;
				  case 4:
				    tmpInfo.Time.Year = MULTIPLY_BY_10(Buf[i] - 0x30);
					DCnt++;
					break;
				  case 5:
				    tmpInfo.Time.Year += (Buf[i] - 0x30);
					DCnt++;
					break;
				  default:
				    break;
				}
			    break;
			  default:
			    break;
			}
		    break;
		  case GPS_GGA:
		    break;
		  case GPS_GLL:
		    break;
		  case GPS_GSA:
		    break;
		  case GPS_GSV:
		    break;
		  case GPS_VTG:
		    break;
		  default:
		    break;
		}
	  }
	}
  }
  else
    MyInfo.Busy = 2;
  if (Type == GPS_RMC)
  {
    temp =  CheckTimeValid(TIME_SRC_GPS, (Uns *)&tmpInfo.Time);
	if (temp == 1)
	{
	  //此处�UTC 时间转换成北京时间
	  ConvertGPSTime((Uns *)&(tmpInfo.Time.Second));
	  memcpy((void *)Info, (void *)&tmpInfo, sizeof(GPS_INFO) - 4);//转换后的经纬度不拷贝
	  //if (tmpInfo.State == 'A')
	    //return (1);
	  return (tmpInfo.State);
	}
	else if (temp == 10)///2013.07.15
		return (tmpInfo.State);
  }
  return(0);
}


/////////////////////////////////////////////////////////////////////////////
//                    Receive GPS data
/////////////////////////////////////////////////////////////////////////////
Uns GPS_CheckSum(Uns *Buf, Uns Len)
{
  Uns i, Data;

  Data = *Buf;
  for (i = 1; i < Len; i++)
    Data ^= Buf[i];
  return (Data & 0xFF);
}


/*
 * convert Longitude_Latitude to longitude and latitude(unit: 0.001')
 * bits: Used to tell the bit length of every LonLat byte.(8 or 16)
 *       convert Longitude_Latitude to bytes[0]...bytes[8].
 * bytes[]:0  1  2  3  4       5  6   7  8
 *     lon:D DD MM.MM MM  lat:DD MM. MM MM
 */
#pragma CODE_SECTION(GPS_ConvertLonLat, "FuncsMap2H0SARam")
void GPS_ConvertLonLat(Uns *lonlat, Uns bits, LgUns *longitudereturn, LgUns *latitudereturn)
{
	LgUns lon, lat;
	Uns temp, bytes[9],i;

	if (bits == 8)
	{
		memcpy(bytes, lonlat, 9);
	}
	else
	{
		for(i=0;i<4;i++)
		{
			bytes[2*i]   = lonlat[i] &  0xFF;
			bytes[2*i+1] = lonlat[i] >> 8;
		}
		bytes[8] = lonlat[4] & 0xFF;
	}

	//度换成分
	lon = MULTIPLY_BY_100(bytes[0]) + (MULTIPLY_BY_10(bytes[1] >> 4) + (bytes[1] & 0x0F));
	lon = MULTIPLY_BY_60(lon);
	//加上分，乘以100，换成0.01分
	lon += (MULTIPLY_BY_10(bytes[2] >> 4) + (bytes[2] & 0x0F));
	lon = MULTIPLY_BY_100(lon);
	//加上 0.01分，乘以10，换成0.001分
	lon += (MULTIPLY_BY_10(bytes[3] >> 4) + (bytes[3] & 0x0F));
	lon = MULTIPLY_BY_10(lon);
	//加上 0.001'，舍弃 0.0001'（x/10 近似为 x / 8 - x*13 / 512 = x*51/512)
	temp = MULTIPLY_BY_10(bytes[4] >> 4) + (bytes[4] & 0x0F);
	lon += ((temp >> 3) - ((temp * 13) >> 9));
	*longitudereturn = lon;

	//latitude:ddmm.mmmm
	//将度转换为分
	//加上分，乘以100，换成0.01分
	lat = MULTIPLY_BY_60(MULTIPLY_BY_10(bytes[5] >> 4) + (bytes[5] & 0x0F)) +
        (MULTIPLY_BY_10(bytes[6] >> 4) + (bytes[6] & 0x0F));
	lat = MULTIPLY_BY_100(lat);
	//加上 0.01分，乘以10，换成0.001分
	lat += (MULTIPLY_BY_10(bytes[7] >> 4) + (bytes[7] & 0x0F));
	lat = MULTIPLY_BY_10(lat);
	//加上 0.001'，舍弃 0.0001'（x/10 近似为 x / 8 - x*13 / 512 = x*51/512)
	temp = MULTIPLY_BY_10(bytes[8] >> 4) + (bytes[8] & 0x0F);
	lat += ((temp >> 3) - ((temp * 13) >> 9));
	*latitudereturn = lat;
}




